Use case: OPAMP in PGA mode

This use case employs the OPAMP (operational amplifier) in PGA (Programmable Gain Amplifier) mode to boost a differential analog signal. The amplified output is then digitized by the ADC (Analog-to-Digital Converter) for further processing.

Description of usage

Description

HAL1

HAL2

OPAMP initialization

Set OPAMP parameters and initialize

  • Set instance, mode, inputs, gain, trimming

  • HAL_OPAMP_Init()

  • HAL configures OPAMP1 peripheral and gain to 2 (PGA mode)

Initialize OPAMP peripheral and set gain

  • HAL_OPAMP_Init()

  • HAL_OPAMP_SetConfig()

  • HAL_OPAMP_SetGain()

  • HAL configures OPAMP1 peripheral and gain to 2 (PGA mode)

ADC initialization

Configure ADC parameters and channel:

  • Set resolution, alignment, scan mode, etc.

  • HAL_ADC_Init()

  • HAL_ADC_ConfigChannel()

Initialize ADC peripheral and configure advanced features

  • HAL_ADC_Init()

  • HAL_ADC_SetConfigPostProcessing()

  • HAL_ADC_SetConfigLowPower()

  • HAL_ADC_REG_SetConfig()

  • HAL_ADC_SetConfigChannel()

Start OPAMP and ADC

Enable OPAMP and start ADC conversion

  • HAL_OPAMP_Start()

  • HAL_ADC_Start()

Enable OPAMP and start ADC conversion with status check

  • HAL_OPAMP_Start()

  • HAL_ADC_Start()

Continuous ADC reading loop

Poll for ADC conversion completion and retrieve value

  • HAL_ADC_PollForConversion()

  • ADC conversion complete

  • uint32_t adcValue = HAL_ADC_GetValue()

  • Process adcValue (amplified difference signal)

Poll ADC for conversion and read value continuously

  • HAL_ADC_REG_PollForConv()

  • ADC conversion complete

  • uint32_t adcValue = HAL_ADC_REG_GetValue()

  • Process adcValue (amplified difference signal)

Stop OPAMP and ADC

Stop OPAMP and ADC when no longer needed

  • HAL_OPAMP_Stop()

  • HAL_ADC_Stop()

Stop OPAMP and ADC when no longer needed

  • HAL_OPAMP_Stop()

  • HAL_ADC_Stop()

Sequence diagram

HAL OPAMP in PGA mode

  @startuml
  participant "Main" as Main
  participant "HAL Library" as HAL
  participant "RCC Peripheral" as RCC
  participant "OPAMP Peripheral" as OPAMP
  participant "ADC Peripheral" as ADC

  == System Initialization ==
  Main -> HAL: HAL_Init()
  note right: Initialize HAL library\nand system peripherals

  Main -> RCC: SystemClock_Config()
  note right: Configure system clock\nfor proper timing

  == GPIO Configuration for OPAMP Inputs ==
  Main -> HAL: Configure analog input pins\nfor OPAMP inputs (VIN+, VIN-)
  HAL --> Main: Pins configured
  note right: Set GPIO pins to analog mode\nDisable digital input/output

  == OPAMP Initialization ==
  Main -> HAL: Set Instance = OPAMP1
  Main -> HAL: Set Mode = PGA mode
  Main -> HAL: Set NonInvertingInput = IO0 (VIN+)
  Main -> HAL: Set InvertingInput = IO1 (VIN-)
  Main -> HAL: Set PgaGain = 2 (adjustable gain)
  Main -> HAL: Set UserTrimming = Factory
  Main -> HAL: HAL_OPAMP_Init(OPAMP1)
  HAL -> OPAMP: Initialize OPAMP with specified parameters\nGain controls amplification factor

  == ADC Initialization ==
  Main -> ADC: Set Instance = ADC1
  Main -> ADC: Configure ADC parameters\n(resolution, data alignment, scan mode, etc.)
  Main -> HAL: HAL_ADC_Init(ADC1)
  HAL --> Main: HAL_OK
  note right: Prepare ADC peripheral for conversion

  Main -> ADC: Configure ADC channel = OPAMP1 output
  Main -> HAL: HAL_ADC_ConfigChannel()
  HAL --> Main: HAL_OK
  note right: Select ADC channel connected to OPAMP output\nfor analog-to-digital conversion

  == Start OPAMP and ADC ==
  Main -> HAL: HAL_OPAMP_Start(OPAMP1)
  HAL --> Main: HAL_OK
  note right: Enable OPAMP to start amplification

  Main -> HAL: HAL_ADC_Start(ADC1)
  HAL --> Main: HAL_OK
  note right: Start ADC conversion process

  == Continuous ADC Reading Loop ==
  loop Continuous ADC Read
      Main -> HAL: HAL_ADC_PollForConversion(ADC1, timeout)
      HAL --> Main: HAL_OK
      note right: Wait until ADC conversion is complete

      Main -> HAL: HAL_ADC_GetValue(ADC1)
      HAL --> Main: adcValue
      note right: Retrieve converted digital value

      Main -> Main: Process adcValue
      note right: Use adcValue for further processing\n(e.g., filtering, display, control)
  end
  @enduml

Code snippet

HAL1

HAL2

OPAMP_HandleTypeDef hopamp1;
ADC_HandleTypeDef hadc1;






void SystemClock_Config(void);

int main(void)
{
    HAL_Init();
    SystemClock_Config();

    hopamp1.Instance = OPAMP1;

    // Configure opamp in differential amplifier mode
    hopamp1.Init.Mode = OPAMP_PGA_MODE;
    hopamp1.Init.NonInvertingInput = OPAMP_NONINVERTINGINPUT_IO0;
    hopamp1.Init.InvertingInput = OPAMP_INVERTINGINPUT_IO1;
    hopamp1.Init.PgaGain = OPAMP_PGA_GAIN_2;
    hopamp1.Init.UserTrimming = OPAMP_TRIMMING_FACTORY;

    if (HAL_OPAMP_Init(&hopamp1) != HAL_OK)
    {
        // Initialization Error
        Error_Handler();
    }

    ADC_ChannelConfTypeDef sConfig = {0};

    hadc1.Instance = ADC1;
    hadc1.Init.ClockPrescaler = ADC_CLOCK_SYNC_PCLK_DIV4;
    hadc1.Init.Resolution = ADC_RESOLUTION_12B;
    hadc1.Init.DataAlign = ADC_DATAALIGN_RIGHT;
    hadc1.Init.ScanConvMode = ADC_SCAN_DISABLE;
    hadc1.Init.EOCSelection = ADC_EOC_SINGLE_CONV;
    hadc1.Init.LowPowerAutoWait = DISABLE;
    hadc1.Init.ContinuousConvMode = ENABLE;
    hadc1.Init.NbrOfConversion = 1;
    hadc1.Init.DiscontinuousConvMode = DISABLE;
    hadc1.Init.ExternalTrigConv = ADC_SOFTWARE_START;
    hadc1.Init.ExternalTrigConvEdge = ADC_EXTERNALTRIGCONVEDGE_NONE;
    hadc1.Init.DMAContinuousRequests = DISABLE;
    hadc1.Init.Overrun = ADC_OVR_DATA_PRESERVED;

    if (HAL_ADC_Init(&hadc1) != HAL_OK)
    {
        Error_Handler();
    }




























    // Configure ADC channel connected to OPAMP output
    sConfig.Channel = ADC_CHANNEL_OPAMP1; // Channel connected to OPAMP1 output
    sConfig.Rank = ADC_REGULAR_RANK_1;
    sConfig.SamplingTime = ADC_SAMPLETIME_247CYCLES_5;

    if (HAL_ADC_ConfigChannel(&hadc1, &sConfig) != HAL_OK)
    {
        Error_Handler();
    }
    // Start the opamp
    if (HAL_OPAMP_Start(&hopamp1) != HAL_OK)
    {
        // Error handling
        Error_Handler();
    }

    // Start ADC
    if (HAL_ADC_Start(&hadc1) != HAL_OK)
    {
        // Error handling
        Error_Handler();
    }

    while (1)
    {
        // Poll ADC conversion
        if (HAL_ADC_PollForConversion(&hadc1, HAL_MAX_DELAY) == HAL_OK)
        {
            uint32_t adcValue = HAL_ADC_GetValue(&hadc1);
            // adcValue now contains the amplified difference signal
            // Process adcValue as needed
        }
    }
}


void Error_Handler(void)
{
    // User can add error handling here
    while (1)
    {
    }
}
hal_opamp_handle_t hopamp1;
hal_adc_handle_t hadc1;
hal_opamp_config_t hconfig;
hal_adc_config_t adc_config;
hal_adc_post_processing_config_t adc_config_post_processing;
hal_adc_low_power_config_t adc_config_low_power;
hal_adc_reg_config_t adc_reg_config;
hal_adc_ovs_config_t adc_ovs_config;
hal_opamp_config_input_connection_t hconfig_input;

void SystemClock_Config(void);

int main(void)
{
    HAL_Init();
    SystemClock_Config();


    // Configure opamp in differential amplifier mode
    hconfig.configuration_mode = HAL_OPAMP_MODE_PGA;
    hconfig_input.inverting_input = HAL_OPAMP_INVERTING_INPUT_GPIO_1;
    hconfig_input.non_inverting_input = HAL_OPAMP_NON_INVERTING_INPUT_GPIO ;




    if (HAL_OPAMP_Init(&hopamp1,OPAMP1) != HAL_OK)
    {
        // Initialization Error
        Error_Handler();
    }


    if (HAL_OPAMP_SetConfig(&hopamp1, &hconfig) != HAL_OK)
    {
        Error_Handler();
    }

    if (HAL_OPAMP_SetConfigInputConnection(&hopamp1, &hconfig_input) != HAL_OK)
    {
        Error_Handler();
    }

    HAL_OPAMP_SetGain(&hopamp1,HAL_OPAMP_PGA_GAIN_2);

    if (HAL_ADC_Init(&hadc1, ADC1) != HAL_OK)
    {
        Error_Handler();
    }

    hadc1.Init.ClockPrescaler = HAL_ADC_CLOCK_SYNC_DIV4;
    hadc1.Init.Resolution = HAL_ADC_RESOLUTION_12_BIT;

    adc_config_post_processing.left_bit_shift = HAL_ADC_LEFT_BIT_SHIFT_NONE;
    if (HAL_ADC_SetConfigPostProcessing(hadc, &adc_config_post_processing) != HAL_OK)
    {
        Error_Handler();
    }

    adc_config_low_power.lp_auto_wait = HAL_ADC_LP_AUTO_WAIT_DISABLE;
    if (HAL_ADC_SetConfigLowPower(hadc, &adc_config_low_power) != HAL_OK)
    {
        Error_Handler();
    }

    adc_reg_config.sequencer_mode = HAL_ADC_REG_SEQ_FIXED;
    adc_reg_config.continuous = HAL_ADC_REG_CONV_CONTINUOUS;
    adc_reg_config.sequencer_length = 1;
    adc_reg_config.sequencer_discont = HAL_ADC_REG_SEQ_DISCONT_DISABLE;
    adc_reg_config.trigger_src = HAL_ADC_REG_TRIG_SOFTWARE_START;
    adc_reg_config.trigger_edge = HAL_ADC_REG_TRIG_EDGE_NONE;
    adc_reg_config.data_transfer = HAL_ADC_REG_DATA_TRANSFER_NONE;
    adc_reg_config.overrun = HAL_ADC_REG_OVR_DATA_PRESERVED;
    if (HAL_ADC_REG_SetConfig(hadc, &adc_reg_config) != HAL_OK)
    {
        Error_Handler();
    }


    // Configure ADC channel connected to OPAMP output
    adc_channel_config.sequencer_rank = 1;
    adc_channel_config.sampling_time = HAL_ADC_SAMPLING_TIME_247CYCLES_5;
    if (HAL_ADC_SetConfigChannel(hadc, HAL_ADC_CHANNEL_8, &adc_channel_config) != HAL_OK)
    {
        Error_Handler();
    }


    // Start the opamp
    if (HAL_OPAMP_Start(&hopamp1) != HAL_OK)
    {
        // Error handling
        Error_Handler();
    }

    // Start ADC
    if (HAL_ADC_Start(&hadc1) != HAL_OK)
    {
        // Error handling
        Error_Handler();
    }

    while (1)
    {
        // Poll ADC conversion
        if (HAL_ADC_REG_PollForConv(&hadc1, HAL_MAX_DELAY) == HAL_OK)
        {
            uint32_t adcValue = HAL_ADC_REG_GetValue(&hadc1);
            // adcValue now contains the amplified difference signal
            // Process adcValue as needed
        }
    }
}


void Error_Handler(void)
{
    // User can add error handling here
    while (1)
    {
    }
}

Key changes

  1. HAL2 splits configuration from initialization using HAL_OPAMP_SetConfig() (and configures gain with HAL_OPAMP_SetGain()).